Part Number Hot Search : 
ALN0810 7C106 M35V5 30SM60 2SC2189 DW1T1 AM29F0 LA5668N
Product Description
Full Text Search
 

To Download AN1064 Datasheet File

  If you can't view the Datasheet, Please click here to try to view without PDF Reader .  
 
 


  Datasheet File OCR Text:
  AN1064/1098 1/30 application note writing optimized hiware c language for st7 by microcontroller division application team introduction the c language originally created for unix system computers is used now in a wide number of application areas especially in embedded 8-bit microcontroller systems. this choice to ex- tend the c language to micro applications is mainly due to: n its structured language based on data types and enhanced control structures. n its portability to different microcontroller target machines. the purpose of this note is to present how to write an optimized c software application for st7 embedded system programming. the main topics focus on how to write c source code that generates the smallest code and data size. to reach this goal some specific c language ex- tensions have to be used like compiler options and pragmas. this application note is based on the st7 hiware c compiler but some examples can be ap- plied to other st7 c compilers. it is not exhaustive and for more details concerning the st7 hi- ware c compiler please refer to the hicross for st7 manual. 1
2/30 table of contents introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 compiler overview and syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2 writing c for st7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.1 basic type size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.2 local variables and parameters strategy . . . . . . . . . . . . . . . . . . . 4 2.3 parameter passing and function return . . . . . . . . . . . . . . . . . . . . . . 5 2.4 memory allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.4.1 constant memory allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.4.2 variable data memory allocation . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.4.3 code memory allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.5 memory access via pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.6 interrupt handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.6.1 function as interrupt service routine . . . . . . . . . . . . . . . . . . . . 8 2.6.2 interrupt functions and hiware internal variables . . . . . . . 9 2.7 hli assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.7.1 syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.7.2 hli assembler and c language . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.7.3 specific hli assembler features . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3 general c programming rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.1 source and header files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.2 meaningful naming strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3 ansi c language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.4 generic functions vs macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.5 avoiding goto statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.6 static global/local variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.7 volatile qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.8 bitfield structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4 optimizing code in st7 c source modules . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3/30 table of contents 4.1 general approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.2 optimum variable definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.2.1 smallest data type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.2.2 st7 short addressing mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.2.3 volatile qualifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.2.4 static local variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.2.5 union type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.2.6 avoid enum type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.2.7 optimum table and structure access . . . . . . . . . . . . . . . . . . . . 18 4.2.8 masked byte variables instead of bitfields . . . . . . . . . . . . . . . 19 4.2.9 optimized int type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.2.10optimum pointer access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.2.11basic type conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.2.12no optimization: register, auto. . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.3 temporary compiler variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.4 optimum constant definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.5 optimum c statement management . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.5.1 non-relevant c source code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.5.1.1unreachable code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.5.1.2redundant code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 4.5.2 byte size object operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 4.5.2.1optimum basic operations . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 4.5.2.2byte division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 4.5.2.3optimum byte shift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4.5.3 word size object operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4.5.3.1optimum basic operations . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4.5.3.2word multiplication and division . . . . . . . . . . . . . . . . . . . 26 4.5.4 conditional statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 4.5.4.1if statement instead of switch . . . . . . . . . . . . . . . . . . . . . 26 4.5.4.2test condition order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 4.5.4.3if statements and assignments . . . . . . . . . . . . . . . . . . . . . 27 4.6 optimum function management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.6.1 functions vs macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.6.2 function parameters and return value . . . . . . . . . . . . . . . . . . 28 4.6.3 function parameter declaration order . . . . . . . . . . . . . . . . . 29 5 conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
compiler overview and syntax 4/30 1 compiler overview and syntax the st7 hiware c compiler is an application which can be launched either through a batch command (from the make file for instance) or an interactive window interface. in both cases the command line has the following structure: note : if in the active default.env file the compoptions variable is filled with default com- piler options, these options are taken into account for each compilation. 2 writing c for st7 2.1 basic type size as the ansi c specifies that the size of the basic types is given by the architecture of the target microcontroller, the following table gives the default format for the st7. 2.2 local variables and parameters strategy usually in most compilers the local variables and parameters are stored in the stack. to gen- erate the most efficient code for the st7 architecture, the hiware c compiler does not use the stack for this purpose. a dedicated ram area (called overlap) where the data are over- lapped as much as possible with reference to the execution structure is preferred. type default format default value range format available with -t option min max (unsigned) char 8bit 0255 8bit, 16bit, 32bit see the hicross for st7 manual for more details option signed char -128 127 unsigned int 16bit 0 65535 (signed) int -32768 32767 unsigned short 0 65535 (signed) short -32768 32767 enum -32768 32767 unsigned long 32bit 0 4294967295 (signed) long -2147483648 2147483647 float, double i eee32 1.17...e-38f 3.40...e+38f ieee32 c:\hicross\prog\cst7.exe -n -wpd -cni -cc -ou file.c compiler command (only needed in the batch style) compiler options source file to compile
5/30 writing c for st7 in fact, this strategy is due to fact that the st7 instruction set does not allow simple access to the data stored in the stack (like ld a,[sp,#-n] ). the only possibility would have been a two instruction solution for each stack data access ( ld x,s followed by ld a,([#0x0100+n,x] where 0x0100 is the stack bottom address and n the data place offset). 2.3 parameter passing and function return as it is described in the previous paragraph, by default the function parameters are stored in the dedicated overlap memory area. but, the last two bytes in the parameter list are also al- ways passed through st7 hardware registers (a and x). the two least significant bytes of the return value are also transferred through these two cpu registers. this technique does not avoid the use of the overlap area but when it is possible, it does some optimization of ram use. 2.4 memory allocation first of all the compiler memory model has to be chosen based on the st7 application type. the following table gives some guidelines for choosing the correct compiler memory model option. * note : global variables can be forced in the page 0 through the pragma data_seg short . compiler option memory model local data parameters global data st7 application type -ms small page 0 page 0 application with all used ram in page 0 -ml large page 0 page 1..n* most efficient code generation for a standard st7 application (local variables and parameters used more often than global data). -mx large extended page 1..n page 1..n* very large st7 application with a lot of local variables and parameters which can not be stored in page 0 char functionname (char prmn, ..., char prm1, char prm0) a register a register (int: + x register) x register overlap area the overlap area is used to store these 2 parameters when a and x are needed for computation in the function. char addchar (char p1, char p2) { return(p2+p1); } 0000 bf 00 [4] ld p1,x 0002 bb 00 [3] add a,p1 0004 81 [6] ret only p1 is stored in the overlap area
writing c for st7 6/30 2.4.1 constant memory allocation c language constant are declared with a const keyword. by default, the hiware c compiler al- locates constants in the default_ram area. to force the constant memory allocation in the rom_var area the -cc compiler option has to be activated. note : the rom_var keyword has always to be defined in the linker parameter file. when a constant has to be allocated in a specific rom area (not in the default one), the pragma const_seg has to be used (this pragma is valid up to the next const_seg pragma). 2.4.2 variable data memory allocation by default variables are allocated in the default_ram area. in st7 applications some var- iables must have fixed addresses (hardware register definitions or variables forced in page 0). in ansi style, the only way to do this is to directly use the address and the preprocessor ca- pability. the drawback of this method is that real c variables are not used which makes the debugging task harder. to resolve this, the st7 hiware c compiler provides the data_seg pragma. with this pragma variables can be allocated to a specific memory area. when variables are allocated to page 0 (from 0x0000 to 0x00ff), the compiler has to know this information to minimize the code when they are used. this allocation is done through the pragma qualifier short . the st7 hiware linker allocates memory sequentially in the order of declaration and optimizes the data memory space when a variable is not used in the application. due to this optimization and as each pragma data_seg is valid up to the next, some care has to be taken when declaring hardware registers. in fact, to avoid hardware register address const char table[] = {...}; const char *table[] = {...}; #pragma const_seg my_rom const char table[] = {...}; placement declared in the linker parameter file #define var (*(char*) (0x0010)) #pragma data_seg my_ram char var; placement declared in the linker parameter file #pragma data_seg short my_page0 char page0var; placement declared in the linker parameter file
7/30 writing c for st7 shifting, a + symbol has to be added to each object file name in the linker parameter file where there is such a declaration. note : as the pragma data_seg is valid up to the next one, when using it in a header file, always remember to reselect the default_ram area at the end. 2.4.3 code memory allocation in some circumstances, applications need to allocate part of generated code in specific rom area. to allow this, the st7 hiware c compiler provides a pragma called code_seg . this pragma is applied to the code in the same way as the data_seg is applied to the variables. this means that it is valid up to the next pragma statement. #pragma data_seg short reg_area volatile char adcdr; volatile char adccsr; #pragma data_seg default file.c names file.o+ ... placement reg_area in no_init 0x0070 to 0x0072 ... file.prm without the + and if the adcdr register is not used, the adccsr is allocated to address 0x0070 instead of 0x0071. #pragma data_seg short reg_area ... #pragma data_seg default /* end of file */ file.h #include file.h char var; ... file.c without the default pragma, var is allocated to reg_area. placement declared in the prm file #pragma code_seg my_rom void fctname1 (void) {...} ... #pragma code_seg default void fctname2 (void) {...}
writing c for st7 8/30 2.5 memory access via pointer when large memory models are selected (-ml or -mx compiler options), the optimum ac- cess to a data located in page 0 through a pointer can be reached with the use of the near keyword. when the small memory model is selected (-ms compiler option), the only access to a data located outside page 0 through a pointer can only be accessed with the use of the far key- word. 2.6 interrupt handling as the st7 has interrupt management capabilities which are not included in the ansi c standard, specific pragmas are implemented in the hiware compiler. 2.6.1 function as interrupt service routine writing a trap_proc pragma before a function definition will produce the replacement of the ret instruction by an iret one at the exit of this function. note : to secure the unused interrupt vectors, write an empty dummy interrupt function. char * near functionname (char * near ptr) { return ((char * near ) ptr +1); } 0000 ab 01 [2] add a,#0x01 0002 97 [2] ld x,a 0003 4f [3] clr a 0004 a9 00 [2] adc a,#0x00 0006 90 97 [3] ld y,a 0008 9f [2] ld a,x 0009 93 [2] ld x,y 000a 81 [6] ret without near keyword: 0000 4c [3] inc a 0001 81 [6] ret with near keyword: char * far functionname (char * far ptr) { return ((char * far ) ptr +1); } 0000 ab 01 [2] add a,#0x01 0002 97 [2] ld x,a 0003 4f [3] clr a 0004 a9 00 [2] adc a,#0x00 0006 90 97 [3] ld y,a 0008 9f [2] ld a,x 0009 93 [2] ld x,y 000a 81 [6] ret with far keyword: 0000 4c [3] inc a 0001 81 [6] ret without far keyword: #pragma trap_proc void interruptfct (void) {...} ... iret generated code:
9/30 writing c for st7 2.6.2 interrupt functions and hiware internal variables by default the st7 hiware c compiler allocates 3 storage variables for extended operations. these variables called _sex (for indirect storing), _lex (for indirect loading) and _r_z (tem- porary storage) are located in page 0. these variables can be used at any time (not controlled by programmer) in the application, ei- ther in the main program or in the interrupt routines. for this reason, as a first development step, the pragma save_regs has to be used to save these software registers. as a second step, after checking the generated code of the interrupt routine, this pragma can be removed if pos- sible. note : the drawback of using the save_regs pragma is that the code size is increased by 34 bytes, the interrupt latency increased by 34 cycles (4.25s with f cpu =8mhz) and the total du- ration of the interrupt routine execution increased by 79 cycles (9.875s with f cpu =8mhz). char *ptr; *ptr = 0xff; 0000 c6 00 01 [4] ld a,ptr:0x1 0003 b7 01 [4] ld _sex :0x1,a 0005 a6 ff [2] ld a,#0xff 0007 ce 00 00 [4] ld x,ptr 000a bf 00 [4] ld _sex ,x 000c 92 c7 00 [7] ld [ _sex .w],a 000f 81 [6] ret 90 89 [4] push y b6 00 [3] ld a,_r_z 88 [3] push a b6 01 [3] ld a,_lex:0x1 88 [3] push a b6 00 [3] ld a,_lex 88 [3] push a b6 01 [3] ld a,_sex:0x1 88 [3] push a b6 00 [3] ld a,_sex 88 [3] push a ... 84 [4] pop a b7 00 [4] ld _sex,a 84 [4] pop a b7 01 [4] ld _sex:0x1,a 84 [4] pop a b7 00 [4] ld _lex,a 84 [4] pop a b7 01 [4] ld _lex:0x1,a 84 [4] pop a b7 00 [4] ld _r_z,a 90 85 [5] pop y 80 [9] iret #pragma trap_proc save_regs void interruptfct (void) {...} interrupt prolog + 17 bytes + 34 cycles interrupt epilog + 17 bytes + 45 cycles
writing c for st7 10/30 2.7 hli assembler for critical source code specifically written for the st7 microcontroller (mandatory write se- quence, critical software timing...), the c language is not appropriate. to provide a solution hi- ware c compiler provides a powerful hli (high level inline) assembler. 2.7.1 syntax the hiware hli assembler is based on the st7 instruction set (cf. st7 programming manual) and the asm keyword. 2.7.2 hli assembler and c language all c source data objects are directly accessible with the hli assembler (variables, functions, macros...). note : as in the ansi c preprocessor, the # symbol is used for string concatenation, and as the st7 instruction set uses this symbol for immediate values, the hiware c compiler provides a asm ld a,x; asm { ld a,x ld y,a ... } hli assembler block single hli assembler instruction #define cst 10 struct {char field1; char field2;} str; char var, array[10]; ... asm { ld a,0xa100 cp a,#cst ld a,str.field2 ld a,array[4] <=> ld a,array:7 ld a,#var ld a,#low(var) ld a,#high(var) call fct } variable c6 a1 00 [4] ld a,0xa100 a1 0a [2] cp a,#0x0a c6 00 01 [4] ld a,str:0x1 c6 00 07 [4] ld a,array:0x7 a6 00 [2] ld a,#var a6 00 [2] ld a,#var a6 01 [2] ld a,#high(var) cd 00 00 [6] call fct address access direct access to the memory
11/30 writing c for st7 dedicated no_string_constr pragma which disables this preprocessor feature. this pragma is valid for all the source modules. 2.7.3 specific hli assembler features in the hli syntax, the st7 branches and data insertion in the code are possible. the following example shows some possible combinations: notes : 1) the compiler optimizes absolute branches into relative ones whenever possible. 2) in the same way as ansi c labels, the hli assembler labels are valid only in the current function. in hiware hli assembler syntax, only a few operators are available for constant expressions. these are: + - * / (). #pragma no_string_constr #define lda10 ld a,#10 ... asm lda10; a6 0a [2] ld a,#0x0a asm { jp clear dc 0xff clear: clr x skip loop: inc x jrne loop } inc x instruction 0000 20 01 [3] jrt *1 abs=0003 0002 ff [4] ld (x),x 0003 5f [3] clr x 0004 21 [3] skip 0005 5c [3] inc x 0006 26 fd [3] jrne *-3 abs=0005 is skipped in the 1st loop rll asm add a,#12+(2-4)+4*5/2; ab 14 [2] add a,#0x14
general c programming rules 12/30 3 general c programming rules the goal of this chapter is to give some c programming rules to improve the legibility, the port- ability and the robustness of the application c source code. in some circumstances, these rules can help to optimize the generated code size. 3.1 source and header files to get a structured software application, whenever possible associate one header file *.h with each *.c source file. this header file should contain all the extern definitions and macros of the corresponding source file (all data and functions which can be used in other modules). note : the st7 c compiler provides a -wpd option to prevent extern definition omissions. to prevent #include recursions, all header files have to be preprocessed. to avoid the dupli- cation of declarations in several files (*.h and *.c), macro definitions and variable declarations have to be defined in the header file with extern preprocessing. note : in the st7 hiware c compiler a dedicated pragma (called once) can replace the header file preprocessing (file_h). 3.2 meaningful naming strategy for reusable and legible c software modules, try as much as possible to implement a function, variable, preprocessor symbol and module naming strategy. #ifndef file_h #define file_h #ifdef file_c #define ext #else #define ext extern #endif #define macro ... ext char myvar; ... #endif file.h #define file_c #include file.h ... myvar = macro; ... file.c #define mod_macro ... char mod_cvar ; int mod_ifct (void) {...} mod_file.c type uppercase uppercase + mixcase mixcase
13/30 general c programming rules 3.3 ansi c language the most important rule to get the best code portability is to write c program as much as pos- sible in ansi c like language. sometimes, it is better to use pragma instead of specific non- ansi instructions as the unknown pragmas have to be ignored by a compiler. 3.4 generic functions vs macros use generic functions as much as possible instead of macros or specific functions. keep only very simple macros which generates optimum code (less instruction bytes than a call instruction). note : all repeated instruction blocks in the source code have to be shrunk to a single function whenever possible. 3.5 avoiding goto statements to get the most legible source code the goto statement as to be avoided each time there is an alternative. 3.6 static global/local variables for good legibility and a well structured application, the following c language objects have to be declared as static : C a global variable used in the module where it is declared. C a function used only in the module where it is declared. C a permanent local variable in a function. a temporary local variable in a function has always to be declared as a local variable to save ram area using the overlap strategy. 3.7 volatile qualifiers for all microcontroller hardware registers which can have their value modified directly by the hardware (status registers...), the volatile qualifier has to be added to their definition to allow the compiler to disable the register value memory optimization. char exported_var; static char module_var; static void module_fct (void) { ... } void exported_fct (void) { char tmp_local_var; static char perm_local_var; ...}
general c programming rules 14/30 3.8 bitfield structure as ansi c does not specify the bit allocation order in a bitfield, the use of this structure should be avoided for portability reasons. consequently, bitfield structures should not be used for mi- crocontroller hardware register definitions.
15/30 optimizing code in st7 c source modules 4 optimizing code in st7 c source modules 4.1 general approach to get the optimum generated code from the st7 hiware c compiler, the following conditions have to be met: n choose the memory model that suits the application, bearing in mind that the optimum is the small one, then the large one and finally the large extended one (to be avoided if it is possible). when linking with a large memory model, use the near keyword as much as possible when accessing short addressing data with pointers. n choose the best compiler options: -cni : by default the ansi c operations with data type smaller than int have to be promoted to int (integral promotion). with this option, this integral promotion is omitted. be aware that this option can generate some wrong code like the carry mistake in the following example: -ou : this optimization option removes all assignments to local variables not referenced later on in the code. -os / -ot : by default the compiler optimizes the generated code size wise ( -os ). this default option is based mainly on the use of library call statements instead of single level instruction sequences (when -ot option is selected). the following example illustrates this compiler option choice. note : the -ol or -or optimization options have no effect in the st7 hiware c compiler. c6 00 00 [4] ld a,c1 cb 00 00 [4] add a,c2 c7 00 01 [5] ld i1:0x1,a 5f [3] clr x cf 00 00 [5] ld i1,x int i1; char c1, c2; ... i1 = c1 + c2; the byte addition carry is ignored ad 00 [6] callr fctcall a6 01 [2] ld a,#0x01 b7 00 [4] ld c1,a 81 [6] ret 20 00 [3] jrt fctcall void function (char c1) { fctcall(); c1 =1; } -ou c6 00 00[4] ld a,sc1 cd 00 00[6] call _sext16 c7 00 01[5] ld i1:0x1,a cf 00 00[5] ld i1,x int i1; signed char sc1; void function (void) { i1 = sc1; ...} -ot c6 00 00 [4] ld a,sc1 5f [3] clr x 4d [3] tnz a 2a 01 [3] jrpl label 5a [3] dec x c7 00 01 [5] label: ld i1:0x1,a cf 00 00 [5] ld i1,x -os
optimizing code in st7 c source modules 16/30 4.2 optimum variable definitions 4.2.1 smallest data type to get the optimum code with a 8-bit microcontroller, the use of the smallest data type size is the best way. in the ansi c language the smallest types are the bit (bitfield) and the char type (8 bits). as the st7 instruction set provides optimum bit handling instructions (bres, bset, btjt, btjf and bcp), the software has to use this structure as much as possible for binary data (this data has always to be located in the page 0). for other data types, char is the preferred data type to get the optimum generated code. using 32-bit variables (floating point arithmetic and long types) on a 8-bit microcontroller is in- herently inefficient and character or integer arithmetic should be used whenever possible. 4.2.2 st7 short addressing mode the st7 instruction set provides three main advantages to variables allocated in page 0 (from address 0x0000 to 0x00ff): n short memory addressing access to get a shorter code. for instance a ld a,var instruction needs two bytes when the variable var is allocated to the page 0 while it needs three bytes when it is allocated outside (30% code size gain). n ability to be directly handled by st7 instructions usually dedicated to cpu registers (inc, dec, clr, cpl, neg, rlc, rrc, sla, sll, sra, srl,swap, tnz).. n bit handling capability (bres, bset, btjt, btjf and bcp instructions). for these three reasons the following variables must be allocated whenever possible in short address memory space (page 0): - all variables which have to be used as bitfields, - the most frequently used standard variables. char c1; #pragma data_seg short zeropage char cz1, #pragma data_seg default ... c1++; cz1++; ... c1 = c1 >> 1; cz1 = cz1 >> 1; ld a,c1 inc a ld c1,a inc cz1 ld a,c1 srl a ld c1,a srl cz1
17/30 optimizing code in st7 c source modules 4.2.3 volatile qualifier to get the optimum generated code, the volatile qualifier has to be used only when it is needed and not systematically for each hardware register. a control register which can be modified only by the software or hardware microcontroller reset does not need to be a vola- tile variable. 4.2.4 static local variable from a legibility point of view the local static definitions are to be used in preference to global ones whenever possible. this guarantees the robustness of the program against wrong static local variable use. in the case of local variable definitions, this qualifier has to be used only for permanent data (not to be overlapped). do not use this static qualifier when it is not needed to avoid removing the overlap optimization for local variables and increasing the used ram size. 4.2.5 union type all global variables which do not have permanent validity during application execution and which are not able to be defined as local variables in a function, have to be grouped together and optimized into union type structures. the use of this method allows optimum ram alloca- tion for global variables as it is automatically done with the overlap segment for the param- eters and local variables. note : the var1 value is overwritten during the application execution by the var2 one. padr is the data register of the port a and can be modified in input mode by the hardware while the paddr can only be modified by soft- ware or by a hardware reset. volatile char padr; volatile char paddr; void fct1 (void) { static char var; var++; ... } void fct2 (void) { static char var; var=0; ... } permanent life temporary life (program) (function) union { char var1; char var2; } varunion; void main (void) {... varunion.var1 = 10; ... varunion.var2 = 23; ...} var2 used main loop var1 used
optimizing code in st7 c source modules 18/30 4.2.6 avoid enum type in the ansi c standard the enum type is based on the int type. this means that all enumerated elements are defined by two bytes for an st7 target. for this reason and in order to generate optimum code, this enum type has to be avoided and replaced by preprocessor #define com- mand (bit or byte format). 4.2.7 optimum table and structure access to get the optimum code size for this table and structure data, each data has to fit as much as possible into a 256-byte memory space to allow the compiler to use the powerful indexed memory access of the st7 instruction set. enum {true, false} binary; if (binary == true)... enum {enum1, enum2, ... enumn} list; list = enum2; char varbin; #define binary 0x01 /* select bit 0.*/ if (varbin & binary)... char list; #define enum1 1 #define enum2 2 list = enum2; ld x,c2 ld a,(tc2,x) ld (tc1,x),a ld x,#0x25 ld a,([ps1.w],x) ld c1,a ld x,c2 ld a,(s1:0x0b,x) ld c2,a ld a,#ts1:0x4c ld ps1:0x1,a ld a,#high(ts1:76) ld ps1,a ld x,c1 ld a,#0x26 mul x,a ld x,a ld a,#0x01 ld (ts1,x),a char c1, c2; char tc1[20], tc2[10]; struct stype { char f1; int f2; char f3[8]; char f4[25]; char f5, f6; }; struct stype s1, ts1[3]; #pragma data_seg short zeropage struct stype *ps1; #pragma data_seg default ... tc1[c2] = tc2[c2]; ... c1 = ps1->f6; ... c2 = s1.f4[c2]; ... ps1 = &ts1[2]; ... ts1[c1].f1 = 1;
19/30 optimizing code in st7 c source modules the structure and table memory alignment allocation is done according to the defined com- plex type without creating memory holes. based on the previous example, the memory imple- mentation of the ts1 table is the following: 4.2.8 masked byte variables instead of bitfields the ansi c language provides a bitfield structure definition with direct access to the bit data through a syntactic combination. the st7 c compiler optimizes the code and generates bres, bset, btjt, btjf and bcp instructions when using this bitfield structure (when it is allocated to page 0). note : for more details concerning the bit order assignment in the bitfield please refer to the hicross for st7 manual. but, as the ansi c does not specify the bit assignment order in a bitfield structure, this struc- ture is not suitable for generating portable microcontroller code especially when used for hard- ware register definition. then facing this limitation, the use of basic type such as char combined with mask expression is preferable. the main advantages are: n optimum bit instruction code (bit instructions whenever possible and optimum) n optimum byte instruction code (byte assignment when optimum) n portability (bit assignment order defined by the programmer) .f1 .f2 .f3[0] .f3[7] .f4[0] .f4[24] .f5 .f6 38 bytes ts1[0] ts1 ts1[1] ts1[2] bset vbf,#2 btjf vbf,#0,label bres vbf,#1 label: #pragma data_seg short zeropage struct { unsigned intb0:1; unsigned intb1:1; unsigned intb2:1;} vbf; #pragma data_seg default ... vbf.b2 = 1; if (vbf.b0) vbf.b1 = 0;
optimizing code in st7 c source modules 20/30 the following example illustrates these advantages and shows the purpose of the -onbf com- piler option.this option is mainly needed when handling hardware register bit where the set- ting and clearing sequences are critical. the following examples describe two masking methods for bit handling. these two methods are based on preprocessor macros which generate optimum code when the data is located in page 0. the first example is based on two parameter macros like the bit instruction set in the st7 as- sembler. to get the optimum code each var variable has to be located in page 0. the second method is based on one parameter macro. this single parameter is the bit ad- dress in page 0 of the data to be manipulated. this bit address can be calculated using the following expression: bit@ = (byte@ x 8) + (7 - bit_place) macro name macro c source code generated code #define setbit(var, place) ( var |= (1 << place) ) bset var,#place #define clrbit(var, place) ( var &= ( (1 << place) ^ 255 ) bres var,#place #define valbit(var, place) ( var & (1 << place) ) btjt var,#place, label btjf var,#place, label macro name macro c source code generated code #define bitset(bit) ( *((unsigned char*) (bit/8)) |= (~(1<<(7-bit%8))) ) bset ...,#... #define bitclr(bit) ( *((unsigned char*) (bit/8)) &= (1<<(7-bit%8)) ) bres ...,#... #define bitval(bit) ( *((unsigned char*) (bit/8)) & (1<<(7-bit%8)) ) btjt ...,#...,label btjf ...,#...,label 1a 00 [5] bset vb,#5 17 00 [5] bres vb,#3 b6 00 [3] ld a,vb aa f2 [2] or a,#0xf2 b7 00 [4] ld vb,a #pragma data_seg short zeropage char var; #pragma data_seg default ... var |= 0x20; var &= 0xf7; var |= 0x22; code optimized without the -onbf compiler option
21/30 optimizing code in st7 c source modules 4.2.9 optimized int type the st7 is an 8 bit microcontroller so it is not optimized for int type variable handling (2 bytes). nevertheless, all simple accesses to two byte variables are reduced to the minimum code size. 4.2.10 optimum pointer access as the st7 instruction set allows indirect memory access only on pointers located in the page 0, these pointers have to be allocated as much as possible in the short access memory area to get the optimum generated code. 4.2.11 basic type conversion in st7 embedded applications, it is usual to convert basic types such as int to char and con- versely. here are some ways of converting these basic types in c language: note : the same conversion can be applied to 32 bit types keeping an optimum generated code. char c1; int i1, i2, ti1[10]; ... i1 = i2; ... i1 = ti1[c1]; ld x,c1 sll x ld a,(ti1:0x1,x) ld i1:0x1,a ld a,(ti1,x) ld i1,a ld a,i2:0x1 ld i1:0x1,a ld x,i2 ld i1,x c6 00 01[4] ld a,p1:0x1 b7 01 [4] ld _lex:0x1,a ce 00 00[4] ld x,p1 bf 00 [4] ld _lex,x 92 c6 00[6] ld a,[_lex.w] c7 00 00[5] ld c1,a 92 c6 00[6] ld a,[p2.w] c7 00 00[5] ld c2,a char c1, c2, *p1; #pragma data_seg short zeropage char *p2; #pragma data_seg default ... c1 = *p1; ... c2 = *p2; p2 in page 0: optimum ld a,word1:0x1 ld lsb,a ld x,a ld a,word1 ld msb,a ld word2:0x1,x ld word2,a #define lsb(word)word #define msb(word)word>>8 #define word(msb,lsb)(int) ((int) msb << 8) + lsb char msb, lsb; int word1, word2; ... lsb = lsb(word1); msb = msb(word1); word2 = word(msb, lsb);
optimizing code in st7 c source modules 22/30 4.2.12 no optimization: register, auto. as the st7 is an accumulator-based machine, the ansi c register and auto qualifiers have no meaning. in fact, the compiler optimizes the code using the a, x and y cpu registers as much as possible. 4.3 temporary compiler variables for some complex c expressions, the compiler has to use temporary variables to solve the operations. these temporary variables can be: n st7 cpu registers (a, x or y) n hiware software registers (_sex, _lex or _r_z) n stack locations (using push and pop instructions) n spills temporary variables (spill_0, spill_1...) the spills temporary variables are managed by the compiler like the local variables and the parameters, which means that they are allocated to the overlap memory segment. note : for specific applications where stack management is critical, the compiler -cns option has to be used to avoid the stack location being used for temporary storage. 4.4 optimum constant definitions in an embedded microcontroller application two kinds of constant definitions exist: n the simple constant values n the data constant structure (fixed data lists, function pointer tables...) both of these constants have to be allocated to the rom area (see section 2.4 ). char c1, c2; void f (void); void function (void) { char c = c1; f(); c2 = c; ...} ld a,c1 push a call f pop a ld c2,a ld a,c1 ld spill_0,a call f ld a,spill_0 ld c2,a -cns
23/30 optimizing code in st7 c source modules when a simple constant value has to be used in an expression, it always has to be defined through the preprocessor #define command and not through a const variable to avoid rom space being unnecessarily allocated to constant values. on the other hand, for data constants which have to be accessed like tables or for strings which have to be used several time during an application, using the const variable is the op- timum solution. note : the st7 c compiler generates the most optimum code either using the #define com- mand or a const variable. when a const variable is used, it is allocated as data only when it is mandatory (indexed access...) else the compiler replaces the constant value directly in the code. 4.5 optimum c statement management 4.5.1 non-relevant c source code 4.5.1.1 unreachable code the st7 c compiler does some automatic optimization for unreachable code which is usually a sign of a programmer error. a6 03 [2] ld a,#0x0a b7 00 00 [5] ld c1,a #define const1 10 const char const2 = 10; char c1; ... c1 = const1; ... c1 = const2; (with -c c option) a6 02 [2] ld a,#0x02 b7 00 00 [5] ld c1,a ... ce 00 00 ld x,c2 d6 00 00 ld a,(const,x) c7 00 00 ld c1,a const char const[] = {1,2,3}; char c1, c2; ... c1 = const[1]; ... c1 = const[c2]; a6 03 [2] ld a,#0x03 b7 00 00 [5] ld c1,a ... a6 05 [2] ld a,#0x05 b7 00 00 [5] ld c2,a char c1, c2; ... c1=2; c1=3; ... goto label; c1=4; label: c2=5;
optimizing code in st7 c source modules 24/30 4.5.1.2 redundant code the st7 c compiler does some automatic optimization for redundant code which is usually a sign of a programmer error. 4.5.2 byte size object operations the main byte size object in the c language for st7 is the basic standard char type. 4.5.2.1 optimum basic operations the following example illustrates the efficiency of the byte object used in basic c expressions. 4.5.2.2 byte division as the st7 instruction set does not provide a division capability, the application has to be written as much as possible with power of 2 divisions in order to get the optimum generated code with shift instructions. otherwise the generated code has to call the hicross library and with a resulting increase in rom size needs. note : for more details on the hicross library, please refer to the hicross for st7 manual. char c1, c2; ... c1 + c2; ... c1 += 0; ... c1 |= c1; compiler warning message. no code generation char c1, c2, c3; ... c1 = c2; ... c1 = c2 + c3; ... c1 = c2 - c3; ... c1 = c2 * c3; ld a,c2 add a,c3 ld c1,a ld a,c2 ld c1,a ld a,c2 sub a,c3 ld c1,a ld a,c3 ld x,c2 mul x,a ld c1,a char c1, c2, c3; ... c1 = c2 / 64; ... c1 = c2 / 63; ld a,c3 ld x,#0x3f call _bdivu ld c2,a ld a,c2 swap a and a,#0x0f srl a srl a ld c1,a
25/30 optimizing code in st7 c source modules 4.5.2.3 optimum byte shift inside an st7 embedded application, it is usual to use shift operations. the st7 c compiler provides optimum code generation using swap and and instructions instead of sequential srl and sll ones when it is the best choice. 4.5.3 word size object operation the basic standard int type is the main word size object (two bytes) in the st7 c language. 4.5.3.1 optimum basic operations for basic operations on int types like additions and subtractions, the corresponding re- sources in the st7 (add, adc, sub, subc instructions) provide an optimum generated code. note : either for integer addition or subtraction the least significant byte is always affected first. this can cause some problems in some critical hardware register settings (16-bit timer counter registers). char c1; ... c1 >>= 3; c1 >>= 4; c1 >>= 5; c6 00 00 ld a,c1 44 srl a 44 srl a 44 srl a c7 00 00 ld c1,a c6 00 00 ld a,c3 4e swap a a4 0f and a,#0x0f 44 srl a c7 00 00 ld c3,a c6 00 00 ld a,c2 4e swap a a4 0f and a,#0x0f c7 00 00 ld c2,a ld a,i2:0x1 sub a,i3:0x1 ld i1:0x1,a ld a,i2 sbc a,i3 ld i1,a int i1, i2, i3; ... i1 = i2 + i3; ... i1++; ... i1 = i2 - i3; ld a,i2:0x1 add a,i3:0x1 ld i1:0x1,a ld a,i2 adc a,i3 ld i1,a ld a,i1:0x1 ld x,i1 inc a jrne label inc x label: ld i1:0x1,a ld i1,x
optimizing code in st7 c source modules 26/30 4.5.3.2 word multiplication and division complex word operations such as multiplication and division need to use the hicross library to solve the requested expression as the st7 cpu does not provide hardware resources for these purposes. note : for more details on the hicross library, please refer to the hicross for st7 manual. 4.5.4 conditional statements 4.5.4.1 if statement instead of switch the ansi c language provides two control statements which can be used for the same se- quential test purpose: if/else and switch/case. the hiware c compiler is better optimized for if/else statements than for switch/case statements so use if/else as much as possible, also for sequential testing. note : using the if/else statement also has the advantage of specifying range conditions. int i1, i2, i3; ... i1 = i2 * i3; ... i1 = i2 / i3; ld x,i2 push x ld a,i2:0x1 push a ld a,i3:0x1 ld x,i3 call _imuls ld i1,x ld i1:0x1,a ld x,i3 push x ld a,i3:0x1 push a ld a,i4:0x1 ld x,i4 call _idivs ld i2,x ld i2:0x1,a if (c1==0) c1=1; else if (c1==10) c1=2; else if (c1==22) c1=3; else if (c1==13) c1=4; else if (c1==45) c1=5; else c1=6; switch (c1) { case 0: c1=1; break; case 10: c1=2; break; case 22: c1=3; break; case 13: c1=4; break; case 45: c1=5; break; default : c1=6; break; } 53 bytes 46 bytes
27/30 optimizing code in st7 c source modules 4.5.4.2 test condition order in terms of execution speed optimization, the test condition with the highest probability to be false has always to be considered first. the second rule to take into account is to place the fastest test conditions first. note : this rule has to be applied for if/else statements but also for all statements condi- tioned by a test (for, while...). 4.5.4.3 if statements and assignments to get the optimum generated code, try as much as possible to include the assignment in the condition. note : this rule has to be applied for if/else statements but also for all statements condi- tioned by a test (for, while...). char c1, c2; ... if (c1 && (c2 & 0x55)) c1 = 0; ... if ((c2 & 0x55) && c1) c1 = 0; same test ld a,c1 jreq end ld a,c2 bcp a,#0x55 jreq end clr a ld c1,a end: ld a,c2 bcp a,#0x55 jreq end ld a,c1 jreq end clr a ld c1,a end: same generated code size char c1, c2; ... if (c1+c2 >= 10)c1 += c2; else c1 = 0; ... if ( (c1+=c2) < 10) c1 = 0; ld a,c1 add a,c2 cp a,#0x0a jrc label1 ld a,c1 add a,c2 jrt label2 label1:clr a label2:ld c1,a ld a,c1 add a,c2 ld c1,a cp a,#0x0a jrnc end clr a ld c1,a end: 23 bytes 17 bytes
optimizing code in st7 c source modules 28/30 4.6 optimum function management 4.6.1 functions vs macros in term of generated code size for short expression sequences, it is usually better to define a preprocessor macro instead of a function (such as variable get/clear functions). given this condition a compromise between generated code size and legibility has to be selected ac- cording to priorities depending on the application. in the first example that follows, the macro solution has been chosen. the major advantage is that the generated code size is minimized each time the var variable is accessed. the draw- back is that there is no security concerning the access of the var variable from an other module. on the contrary, in the second example, the function solution has been chosen. the major advantage is that the var variable is protected against unwanted direct access from another module (declared static in the file.c module). the drawback is related to the ld , call and ret instructions (code size and execution time increased): n in total the generated code size is increased by 4 bytes ( ld , ret ) n each access to the var variable is increased by 12 cycles ( call , ret ). the above data assumes that the var variable is allocated outside page 0. 4.6.2 function parameters and return value as the a and x registers of the st7 are used for parameter passing and the function return value, the c source which generates the optimum code has to contain as many functions as possible with a maximum of two byte size parameters and two byte size return value. extern char var; #define get_value var char var; ... file.h file.c extern char get_value(void); static char var; ... char get_value(void) { return(var); } ... file.h file.c char fct1(int p0) {...} int fct2(char p1, char p0) {...}
29/30 optimizing code in st7 c source modules 4.6.3 function parameter declaration order to optimize the use of the a and x registers for parameter passing, the order of the parame- ters in the parameter definition list has to be reversed compared to the order in which they are used in the function. the following two examples illustrate the importance of the parameter declaration order. n in the first example, the code is optimum with parameter passing through a and x registers for p1 and p0 . n in the second example, the source code is the same as the previous one, only the parameter declaration order has changed. the result of this move is a drastic increase of the generated code size (more than 130%) and of the overlap segment usage (2 more bytes). char fctparam1 (char p2, char p1, char p0) { c1 = p0 * p1; return(p2); } 42 mul x,a c7 00 00 ld c1,a b6 00 ld a,p2 char fctparam2 (char p1, char p0, char p2) { c1 = p0 * p1; return(p2); } bf 00 ld p0,x b7 00 ld p2,a b6 00 ld a,p0 be 00 ld x,p1 42 mul x,a c7 00 00 ld c1,a b6 00 ld a,p2
conclusion 30/30 5 conclusion the st7 hiware c compiler is a powerful tool for developing st7 embedded application in c language. following the rules described in this document provides a major added value to generated the optimum c code for an st7 microcontroller. the present note which is for guidance only aims at providing customers with information regarding their products in order for them to save time. as a result, stmicroelectronics shall not be held liable for any direct, indirect or consequential damages with respect to any claims arising from the content of such a note and/or the use made by customers of the information contained herein in connexion with their products. information furnished is believed to be accurate and reliable. however, stmicroelectronics assumes no responsibility for the co nsequences of use of such information nor for any infringement of patents or other rights of third parties which may result from its use. no license is granted by implication or otherwise under any patent or patent rights of stmicroelectronics. specifications mentioned in this publicati on are subject to change without notice. this publication supersedes and replaces all information previously supplied. stmicroelectronics prod ucts are not authorized for use as critical components in life support devices or systems without the express written approval of stmicroele ctronics. the st logo is a registered trademark of stmicroelectronics ? 1999 stmicroelectronics - all rights reserved. purchase of i 2 c components by stmicroelectronics conveys a license under the philips i 2 c patent. rights to use these components in an i 2 c system is granted provided that the system conforms to the i 2 c standard specification as defined by philips. stmicroelectronics group of companies australia - brazil - canada - china - france - germany - italy - japan - korea - malaysia - malta - mexico - morocco - the neth erlands - singapore - spain - sweden - switzerland - taiwan - thailand - united kingdom - u.s.a. http://www.st.com


▲Up To Search▲   

 
Price & Availability of AN1064

All Rights Reserved © IC-ON-LINE 2003 - 2022  

[Add Bookmark] [Contact Us] [Link exchange] [Privacy policy]
Mirror Sites :  [www.datasheet.hk]   [www.maxim4u.com]  [www.ic-on-line.cn] [www.ic-on-line.com] [www.ic-on-line.net] [www.alldatasheet.com.cn] [www.gdcy.com]  [www.gdcy.net]


 . . . . .
  We use cookies to deliver the best possible web experience and assist with our advertising efforts. By continuing to use this site, you consent to the use of cookies. For more information on cookies, please take a look at our Privacy Policy. X